using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
using SovaDataService.SoDataServices;
using SovaDataService.SovaDataServices;
using SovaDataService.SovaModels;
using SovaWebService.ViewModels;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;

namespace SovaWebService.Controllers
{
    [Route("api/searches")]
    public class SearchController : Controller
    {
        private SearchDataService _searchDataService;
        private QuestionDataService _questionDataService;

        /**
         * Main constructor.
         */
        public SearchController(SearchDataService searchDataService, QuestionDataService questionDataService)
        {
            _searchDataService = searchDataService;
            _questionDataService = questionDataService;
        }

        /**
         * Retrieves the entire search history for account.
         */
        [Authorize]
        [HttpGet(Name = nameof(GetSearchedByAccountId))]
        public IActionResult GetSearchedByAccountId(int page = 0, int pageSize = 10)
        {
            // Retrieve the userId from the JWT Name property.
            int.TryParse(HttpContext.User.Identity.Name, out var userId);

            // Retrieve the search history for the current page.
            var searches = _searchDataService.GetAllForUser(userId)
                                             .Skip(page * pageSize)
                                             .Take(pageSize);
            // Retrieve the number of search results.
            int searchCount = _searchDataService.GetCount(userId);

            // Build a ViewModel for the list of searches.
            var searchList = new SearchListVM();
            searchList.Total = searchCount;

            // Add SearchVM objects to the SearchListVM for each search result.
            foreach (var search in searches)
            {
                searchList.Searches.Add(new SearchVM()
                {
                    Id = search.Id,
                    SearchText = search.SearchText,
                    SearchDate = search.SearchDate
                });
            }

            // Add pagination properties to the object.
            searchList += UrlHelper.Pagination(Url, nameof(GetSearchedByAccountId), page, pageSize, searchCount);

            return Ok(searchList);
        }

        /**
         * Retrieves the questions relevant to the search query
         */
        [Authorize]
        [HttpGet("search/{text}", Name = nameof(Search))]
        public IActionResult Search(string text, int page = 0, int pageSize = 10)
        {
            // Retrieve the userId from the JWT Name property.
            int.TryParse(HttpContext.User.Identity.Name, out var userId);

            // Build a question list view model.
            var questionsList = new QuestionsListVM();
            questionsList.Questions = new List<IQuestionVM>();

            // Return an empty question list when there is no query text.
            if (String.IsNullOrWhiteSpace(text))
            {
                return Ok(questionsList);
            }

            // Retrieve all the questions (using pagination) that match the query text + the question count.
            var questions = _questionDataService.GetQuestionsBySearch(text, userId, out int questionCount)
                                                .Skip(page * pageSize)
                                                .Take(pageSize);
            
            // Add the questions to the question list.
            foreach (var question in questions)
            {
                questionsList.Questions.Add(new QuestionVM()
                {
                    Title = question.Title,
                    Score = question.Score,
                    QuestionUrl = Url.Link(nameof(QuestionsController.GetQuestion), new { id = question.Id }),
                    Body = question.Body,
                    AuthorName = question.Author.Name
                });
            }

            // Add the question count to the view model.
            questionsList.Total = questionCount;

            // Add pagination properties to the view model object.
            questionsList += UrlHelper.Pagination(Url, nameof(Search), page, pageSize, questionCount);

            // Return the question list view model with an OK status.
            return Ok(questionsList);
        }
    }
}